// 第17节：索引：复合索引
/* 
  这节课先来看看什么样的数据你使用索引会变慢，然后学习一下复合索引的使用和语法。通过这节课我们需要对所以使用的时机有所了解，
  避免画蛇添足，产生不必的麻烦。
*/


// 索引中的小坑
/* 
  记得我刚学MongoDB时，学会了索引，我就到处想用，甚至几百条数据的集合(collections)，我也自作聪明的用一下，但结果往往是画蛇
  添足，走了不少弯路。通过实际开发和性能对比，我自己总结了几条不用索引的情况（不一定对，但是自己的经验之谈）。

  1. 数据不超万条时，不需要使用索引。性能的提升并不明显，而大大增加了内存和硬盘的消耗.
  2. 查询数据超过表数据量30%时，不要使用索引字段查询。实际证明会比不使用索引更慢，因为它大量检索了索引表和我们原表。
  3. 数字索引，要比字符串索引快的多，在百万级甚至千万级数据量面前，使用数字索引是个明确的选择。
  4. 把你经常查询的数据做成一个内嵌数据（对象型的数据），然后集体进行索引。
*/


// 复合索引
/* 
  好了上边我们讲了一大堆理论，现在来看复合索引。复合索引就是两条以上的索引。上节课我们已经把username字段建立了索引，
  我们现在把randNum0，这个字段也设置成索引。
*/
// db.randomInfo.ensureIndex({randNum0:1});
/* 
  建立好后,我们再用查询索引状态命令进行查询.
  db.randomInfo.getIndexes();
  这个时候已经是两个自建索引,一共三个索引
  [
      {
              "v" : 2,
              "key" : {
                      "_id" : 1
              },
              "name" : "_id_",
              "ns" : "demo15.randomInfo"
      },
      {
              "v" : 2,
              "key" : {
                      "username" : 1
              },
              "name" : "username_1",
              "ns" : "demo15.randomInfo"
      },
      {
              "v" : 2,
              "key" : {
                      "randNum0" : 1
              },
              "name" : "randNum0_1",  //不管哪个索引, name才是他们唯一ID的标识,删除的时候用的上 dropIndex('randNum0_1')
              "ns" : "demo15.randomInfo"
      }
  ]
*/


// 两个索引同时查询
/* 
  我们同时查询两个索引的值，看看效果是怎么样的。
*/
var startTime=+new Date();
var db=connect('demo15'); //
// var result=db.randomInfo.find({username:'ce4cuy',randNum0:299210});  //为指定
var result = db.randomInfo.find({ username: 'ce4cuy', randNum0: 299210}).hint({randNum0:1}); //指定索引查询
result.forEach(function(val){
  printjson(val);
})
var endTime=+new Date();
print('查询时间为:'+ (endTime-startTime));
/* 
  从性能上看并没有什么特殊的变化，查询时间还是在6ms或者8ms左右。
  重点: MongoDB的复合查询是按照我们的索引顺序进行查询的。  就是我们用db.randomInfo.getIndexes()查询出的数组。
*/


// 指定索引查询（hint）
/* 
  课程开始时，我说了数字的索引要比字符串的索引快，这就需要一个方法来打破索引表的查询顺序，
  用我们自己指定的索引优先查询，  这个方法就是hint().
*/
// var result = db.randomInfo.find({ username: 'ce4cuy', randNum0: 299210 }).hint({ randNum0: 1 }); //指定索引查询
/* 
  由于数据量和复杂成都还是不大，所以你看不出来明显的性能提升，但是要相信技术胖，等工作中遇到大数据时，一定会得到很好的效果的。
*/


// 删除索引
/* 
  当索引性能不佳或起不到作用时，我们需要删除索引，删除索引的命令是dropIndex().
*/
// db.randomInfo.dropIndex('randNum0_1');  //索引唯一的ID
/* 
  这里需要注意的是删除时填写的值，并不是我们的字段名称（key），
  而是我们索引查询表中的name值。这是一个小坑，希望小伙伴们不要踩中。
*/


// 总结:
/* 
  总结：这节主要内容还是操作索引，包括复合索引的建立，删除。和一些使用索引的小窍门。
*/
